﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace lumo.input
{
    /// <summary>
    /// A simple thumbstick using 2 Axes
    /// </summary>
    public class ThumbstickWrapper : IThumbstick
    {
        // Private variables
        private List<IThumbstick> ThumbstickList = new List<IThumbstick>();
        private List<IThumbstick> ThumbstickUpdateList = new List<IThumbstick>();
        private bool LastDown = false;
        private bool CurrentDown = false;
        private float RepeatCount = 0;
        private float _RepeatDelay = Config.DefaultRepeatDelay;
        private float _RepeatTime = Config.DefaultRepeatTime;
        private Vector2 _Vector = Vector2.Zero;

        // The propertie for frame ID
        private uint _FrameID = 0;
        /// <summary>Access for FrameID</summary>
        public uint FrameID { get { return _FrameID; } }

        /// <summary>
        /// Constructor.
        /// </summary>
        public ThumbstickWrapper()
        {
            this.ReverseX = false;
            this.ReverseY = false;
            Repeated = false;
        }

        /// <summary>
        /// Add an object
        /// </summary>
        /// <param name="Object">Object to wrap.</param>
        /// <param name="NeedUpdate">Do you need to update this object?</param>
        public void Add(IThumbstick Object, bool NeedUpdate = true)
        {
            ThumbstickList.Add(Object);
            if (NeedUpdate)
                ThumbstickUpdateList.Add(Object);
            UpdateValues();
        }

        /// <summary>
        /// Clear the list
        /// </summary>
        public void Clear()
        {
            ThumbstickList.Clear();
            ThumbstickUpdateList.Clear();
        }

        /// <summary>
        /// The value
        /// </summary>
        public Vector2 Vector { get { return new Vector2((this.ReverseX ? -_Vector.X : _Vector.X), (this.ReverseY ? -_Vector.Y : _Vector.Y)); } }

        /// <summary>
        /// Reverse?
        /// </summary>
        public bool ReverseX { get; set; }

        /// <summary>
        /// Reverse?
        /// </summary>
        public bool ReverseY { get; set; }

        /// <summary>
        /// The vector of the thumbstick.
        /// </summary>
        private void UpdateValues()
        {
            float XValue = 0;
            float YValue = 0;
            foreach (IThumbstick thumb in ThumbstickList)
            {
                XValue += thumb.Vector.X;
                YValue += thumb.Vector.Y;
            }
            _Vector.X = MathHelper.Clamp(XValue, -1, 1);
            _Vector.Y = MathHelper.Clamp(YValue, -1, 1);
        }

        /// <summary>
        /// Update the axis.
        /// </summary>
        public void Update(LumoComponent Game)
        {
            // Only called once per frame.
            if (_FrameID == Game.FrameID)
                return;
            _FrameID = Game.FrameID;

            // Update the thumbsticks
            foreach (IThumbstick thumb in ThumbstickUpdateList)
                thumb.Update(Game);

            // Update the values.
            UpdateValues();

            LastDown = CurrentDown;
            CurrentDown = (Math.Abs(_Vector.Length()) >= 0.5);
            Repeated = false;
            if (Game == null)
            {
                Repeated = Triggered;
                return;
            }

            if (CurrentDown)
            {
                if (!LastDown)
                {
                    Repeated = true;
                    RepeatCount = _RepeatDelay;
                }
                else
                {
                    RepeatCount -= (float)Game.GameTime.ElapsedGameTime.TotalMilliseconds;
                    if (RepeatCount <= 0)
                    {
                        Repeated = true;
                        RepeatCount = _RepeatTime;
                    }
                }
            }
        }

        /// <summary>
        /// Type of object.
        /// </summary>
        /// <returns>The type of object.</returns>
        public InputType GetInputType() { return InputType.Thumbstick; }

        /// <summary>
        /// Return the Button.
        /// </summary>
        /// <returns>The ID.</returns>
        public long GetInputID() { return 0; }

        /// <summary>
        /// Property to check if key is pressed.
        /// </summary>
        public bool Pressed { get { return CurrentDown; } }

        /// <summary>
        /// Property to check if key is triggered.
        /// </summary>
        public bool Triggered { get { return (CurrentDown && !LastDown); } }

        /// <summary>
        /// Property to check if key is repeated.
        /// </summary>
        public bool Repeated { get; private set; }

        /// <summary>
        /// Property to check if key is released.
        /// </summary>
        public bool Released { get { return (LastDown && !CurrentDown); } }

        /// <summary>
        /// Implemented IInputObject Released.
        /// </summary>
        /// <returns>True if the key is released.</returns>
        public float RepeatDelay { get { return _RepeatDelay; } set { _RepeatDelay = value; } }

        /// <summary>
        /// Implemented IInputObject Released.
        /// </summary>
        /// <returns>True if the key is released.</returns>
        public float RepeatTime { get { return _RepeatTime; } set { _RepeatTime = value; } }
    }
}
